﻿import { WebException } from './webException';
import { Order } from './../domain/model/order';
import { OrderService } from '../service/orderService';
import { CloudSyncService, DataSyncStruct } from '../service/cloudSyncService';
import { Response, ServiceConfig, Guid, route, RequestDataVerify, Obsolete } from "../common";
import { TableService } from '../service/tableService';
import { DataVerification } from './verification/baseVerification';
import { RequestLog } from '../common/http/router/routeDecorators';

export class TableController {
    private tableSvr: TableService;
    private syncSvr: CloudSyncService;
    private orderSvr: OrderService;
    constructor() {
        this.tableSvr = ServiceConfig.Current.GetService<TableService>("tableService");
        this.syncSvr = ServiceConfig.Current.GetService<CloudSyncService>("cloudSyncService");
        this.orderSvr = ServiceConfig.Current.GetService<OrderService>("orderService");
    }

    toString() {
        return "TableController";
    }

    @route({ method: 'get', path: '/api/table/getTableList/:tableZoneId?/:tableStatus?' })
    async getTableList(ctx, next) {
        let params = {
            TableZoneId: null,
            TableStatus: null
        }
        params.TableZoneId = ctx.params.tableZoneId ? ctx.params.tableZoneId : null;
        params.TableStatus = ctx.params.tableStatus ? ctx.params.tableStatus : null;
        let tt = await this.tableSvr.GetTableList(params);
        let tableList = tt.map(x => {
            let r = x.desktable;
            if (x.desktable.status == "opening")
                (<any>r).tableParty = x.tableparty;
            return r;
        });

        // for (let x of tableList) {
        //     if ((<any>x).tableParty && ((<any>x).tableParty.status == "opening" || (<any>x).tableParty.status == "presettled")) {
        //         let masterOrder = await this.orderSvr.GetOrderById((<any>x).tableParty.orderId);
        //         (<any>x).masterOrder = masterOrder;
        //     }
        // }

        // for (let item of tableList) {
        //     if (item.status == "opening") {
        //         let p = await this.tableSvr.GetCurrentTableParty(item.id);
        //         if (p) {
        //             (<any>item).tableParty = p;
        //             if ((p.status == "opening" || p.status == "presettled") && p.orderId) {
        //                 // 获取开台的人数
        //                 let masterOrder = await this.orderSvr.GetOrderById(p.orderId);
        //                 if (masterOrder) {
        //                     delete masterOrder.cart;
        //                     (<any>item).masterOrder = masterOrder;
        //                 }
        //             }
        //         }
        //     }
        // }

        //对台桌进行排序s
        if (!params.TableZoneId) {
            // 分组zone 
            let hist = {};
            tableList.map(a => {
                if (!a.zone) {
                    a.zone = {
                        id: 'null',
                        showOrder: 999
                    };
                }
                if (a.zone.id in hist) hist[a.zone.id].tableList.push(a);
                else hist[a.zone.id] = { showOrder: a.zone.showOrder, tableList: [a] };
            });

            // 转化成数组
            let result = [];
            for (let zoneId in hist) {
                result.push(hist[zoneId]);
            }

            // 排tableZone的顺序
            result = result.sort((a, b) => { return a.showOrder - b.showOrder; });

            let r = [];
            for (let item of result) {
                r = r.concat(item.tableList.sort((a, b) => { return a.showOrder - b.showOrder; }));
            }

            tableList = r;
        }
        else {
            // 兼容处理，内存查询
            tableList = tableList.filter(x => {
                if (x.zone) {
                    return x.zone.id == params.TableZoneId;
                }
                else return false;
            });
            tableList = tableList.sort((a, b) => { return a.showOrder - b.showOrder; });
        }

        ctx.response.body = Response.ok("获取台桌列表成功", tableList);

        await next();
    }

    /**
     * 更新台桌人数
     * 已过时推荐使用 updateTableInfo 
     * @param {any} ctx 
     * @param {any} next 
     * 
     * @memberof TableController
     */
    @route({ method: "put", path: "/api/table/updateHeadCount" })
    @Obsolete("修改台桌人数请使用updateTableInfo")
    async updateTableHeadCount(ctx, next) {
        let masterOrderId = ctx.request.body.masterOrderId;
        let headCount = ctx.request.body.headCount;
        let storeId = ctx.accept.headers["storeid"];
        let terminal = ctx.request.body.terminal;
        let user = ctx.request.body.user;

        let masterOrder = await this.orderSvr.GetOrderById(masterOrderId);
        masterOrder.extended.headCount = headCount;
        await this.orderSvr.UpdateMasterOrder(masterOrder);
        ctx.response.body = Response.ok("更改成功");
        this.syncSvr.DomainDataSyncPackage([
            {
                id: masterOrder.id,
                body: masterOrder,
                entityName: "orders"
            }
        ], {
                storeId: storeId,
                terminal: terminal,
                user: user
            });

        await next();
    }

    @route({ method: "put", path: "/api/table/updateTableInfo" })
    async updateTableInfo(ctx, next) {
        let masterOrderId = ctx.request.body.masterOrderId;
        let headCount = ctx.request.body.headCount;
        let storeId = ctx.accept.headers["storeid"];
        let terminal = ctx.request.body.terminal;
        let user = ctx.request.body.user;
        let tablePartyId = ctx.request.body.tablePartyId;
        let waiter: {
            id: string,
            name: string
        }[] = ctx.request.body.waiter;

        await this.tableSvr.updateTableInfo({
            tablePartyId: tablePartyId,
            waiter: waiter,
            headCount: headCount,
            masterOrderId: masterOrderId
        });
        ctx.response.body = Response.ok("更改成功");

        if (masterOrderId) {
            let masterOrder = await this.orderSvr.GetOrderById(masterOrderId);
            this.syncSvr.DomainDataSyncPackage([
                {
                    id: masterOrder.id,
                    body: masterOrder,
                    entityName: "orders"
                }
            ], {
                    storeId: storeId,
                    terminal: terminal,
                    user: user
                });
        }

        await next();
    }

    @route({ method: 'get', path: '/api/table/getTableZoneList' })
    async getTableZoneList(ctx, next) {
        let res = await this.tableSvr.GetTableZoneList();

        res = res.sort((a, b) => { return a.showOrder - b.showOrder; });

        ctx.response.body = Response.ok("获取台桌分类列表成功", res);
        await next();
    }

    @route({ method: 'put', path: '/api/table/openTable' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.OpenTable())
    async openTable(ctx, next) {
        let table = {
            id: ctx.request.body.id,
            headCount: ctx.request.body.headCount // 开台的人数
        }
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let serialNo = ctx.request.body.serialNo;
        let storeId = ctx.accept.headers["storeid"];
        let sourceid = ctx.request.body.sourceid;
        let waiter: {
            id: string,
            name: string
        }[] = ctx.request.body.waiter;

        if (!storeId) throw new WebException("参数错误， storeId错误！");

        //构造一个台桌主订单
        let masterOrder = new Order();
        masterOrder.storeId = storeId;
        masterOrder.terminalName = terminal.name;
        masterOrder.creatorId = user.id;
        masterOrder.creator = user;
        masterOrder.serialNo = await this.orderSvr.SerialNoMaker();
        masterOrder.sourceid = sourceid ? sourceid : null;
        let result = await this.tableSvr.OpenTable({
            table: <any>table,
            masterOrder: masterOrder,
            waiter: waiter
        });

        ctx.response.body = Response.ok("开台成功", result);

        //将数据同步到Pos
        this.syncSvr.DomainDataSyncPackage([
            {
                id: result.table.id,
                body: result.table,
                entityName: "deskTable"
            },
            {
                id: result.tableParty.id,
                body: result.tableParty,
                entityName: "tableParty"
            },
            {
                id: result.masterOrder.id,
                body: result.masterOrder,
                entityName: "orders"
            }
        ], {
                storeId: storeId,
                terminal: terminal,
                user: user
            }, {
                name: "pos.openTable",
                type: "tablesChanged"
            });
        await next();
    }

    @route({ method: 'put', path: '/api/table/closeTable' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.CloseTable())
    async closeTable(ctx, next) {
        let storeId = ctx.accept.headers["storeid"];
        let tableId: string = ctx.request.body.id;
        let terminal = ctx.request.body.terminal;
        let user = ctx.request.body.user;

        let r = await this.tableSvr.CloseTable(tableId, terminal.id);
        ctx.response.body = Response.ok("关台成功", r);

        let tableParty = (<any>r.table).tableParty;

        //同步关台数据
        this.syncSvr.DomainDataSyncPackage([
            {
                id: r.table.id,
                body: r.table,
                entityName: "deskTable"
            },
            {
                id: tableParty.id,
                body: tableParty,
                entityName: "tableParty"
            },
            {
                id: r.masterOrder.id,
                body: r.masterOrder,
                entityName: "orders"
            }
        ],
            {
                storeId: storeId,
                terminal: terminal,
                user: user
            },
            {
                name: "pos.closeTable",
                type: "tablesChanged"
            });

        await next();
    }

    @route({ method: 'put', path: '/api/table/mergeTable' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.MergeTable())
    async mergeTable(ctx, next) {
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let storeId = ctx.accept.headers["storeid"];
        let mainTable = ctx.request.body.mainTable;
        let tableList = ctx.request.body.tableList;

        //构造一个台桌主订单
        let masterOrder = new Order();
        masterOrder.storeId = storeId;
        masterOrder.terminalName = terminal.name;
        masterOrder.creatorId = user.id;
        masterOrder.creator = user;
        // masterOrder.serialNo = await this.orderSvr.SerialNoMaker();

        let result = await this.tableSvr.MergeTable(mainTable, tableList, masterOrder);
        ctx.response.body = Response.ok("并台成功", result);

        //同步数据
        let syncData = [
            {
                id: result.tableGroup.id,
                body: result.tableGroup,
                entityName: "tableGroup"
            }
        ];

        for (let item of result.tablePartyList) {
            syncData.push({
                id: item.id,
                body: item,
                entityName: "tableParty"
            });
        }

        for (let item of result.masterOrderList || []) {
            syncData.push({
                id: item.id,
                body: item,
                entityName: "orders"
            });
        }

        for (let item of result.tableList || []) {
            syncData.push({
                id: item.id,
                body: item,
                entityName: "deskTable"
            });
        }

        this.syncSvr.DomainDataSyncPackage(syncData, { storeId: storeId, terminal: terminal, user: user }, { name: "pos.mergeTable", type: "tablesChanged" });

        await next();
    }

    @route({ method: 'put', path: '/api/table/cancelMergeTable' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.CancelMergeTable())
    async cancelMergeTable(ctx, next) {
        let tableGroupId = ctx.request.body.tableGroupId;
        let tableId = ctx.request.body.tableId;
        let tablePartyId = ctx.request.body.tablePartyId;
        let masterOrderId = ctx.request.body.masterOrderId;
        let preOrderCount = ctx.request.body.preOrderCount;

        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let storeId = ctx.accept.headers["storeid"];

        let r = await this.tableSvr.CancelMergeTable(tableId, tablePartyId, tableGroupId, masterOrderId, preOrderCount);
        ctx.response.body = Response.ok("取消并台成功", r);

        //取消并台数据同步
        let dataSyncList = [];
        for (let item of r.tablePartyList) {
            dataSyncList.push({
                id: item.id,
                body: item,
                entityName: "tableParty"
            });
        }
        if (r.masterOrder) {
            dataSyncList.push({
                id: r.masterOrder.id,
                body: r.masterOrder,
                entityName: "orders"
            });
        }
        if (r.table) {
            dataSyncList.push({
                id: r.table.id,
                body: r.table,
                entityName: "deskTable"
            })
        }


        this.syncSvr.DomainDataSyncPackage(dataSyncList, { storeId: storeId, terminal: terminal, user: user }, { name: "pos.unMergeTable", type: "tablesChanged" });

        await next();
    }

    @route({ method: 'put', path: '/api/table/transferTable' })
    @RequestLog()
    @RequestDataVerify(new DataVerification.TransferTable())
    async transferTable(ctx, next) {
        let oldTable = ctx.request.body.oldTable;
        let newTable = ctx.request.body.newTable;
        let terminal = ctx.request.body.terminal;
        let user = ctx.request.body.user;
        let storeId = ctx.accept.headers["storeid"];
        let r = await this.tableSvr.TransferTable(oldTable, newTable);
        ctx.response.body = Response.ok("转台成功", r);

        let syncData = [
            {
                id: r.oldTable.id,
                body: r.oldTable,
                entityName: "deskTable"
            },
            {
                id: r.newTable.id,
                body: r.newTable,
                entityName: "deskTable"
            },
            {
                id: r.oldTableParty.id,
                body: r.oldTableParty,
                entityName: "tableParty"
            },
            {
                id: r.newTableParty.id,
                body: r.newTableParty,
                entityName: "tableParty"
            },
            {
                id: r.masterOrder.id,
                body: r.masterOrder,
                entityName: "orders"
            }
        ];
        for (let item of r.preOrderList) {
            syncData.push({
                id: item.id,
                body: item,
                entityName: "preOrders"
            })
        }

        this.syncSvr.DomainDataSyncPackage(syncData, { storeId: storeId, terminal: terminal, user: user }, { name: "pos.tableTrans", type: "tablesChanged" });

        await next();
    }

    @route({ method: 'get', path: '/api/table/getTableInfo/:tableId' })
    async getTableInfo(ctx, next) {
        let tableId: string = ctx.params.tableId;
        let table = await this.tableSvr.GetTableById(tableId);

        if (table.status == "opening") {
            let p = await this.tableSvr.GetCurrentTableParty(table.id);
            if (p) {
                (<any>table).tableParty = p;
                (<any>table).orderList = await this.orderSvr.GetPreOrderByMasterOrder(p.orderId);
                (<any>table).masterOrder = await this.orderSvr.GetOrderById(p.orderId);
            }
        }

        ctx.response.body = Response.ok("获取台桌成功", table);
        await next();
    }

    @route({ method: 'put', path: '/api/table/served' })
    @RequestDataVerify(new DataVerification.Served())
    async served(ctx, next) {
        let params: {
            invertoryId: string;
            orderId: string;
            operator: { id: string, name: string };
            count: number;
            terminal: any;
            user: any;
            cartItemId: string;
        } = ctx.request.body;
        let storeId = ctx.accept.headers["storeid"];
        let preOrder = await this.tableSvr.Served(params.invertoryId, params.cartItemId, params.orderId, params.operator, params.count);

        ctx.response.body = Response.ok("上菜成功！", preOrder);

        //同步数据
        this.syncSvr.DomainDataSyncPackage([
            {
                id: preOrder.id,
                body: preOrder,
                entityName: "preOrders"
            }
        ], { storeId: storeId, terminal: params.terminal, user: params.user }, { name: "", type: "" });

        await next();
    }

    @route({ method: 'put', path: '/api/table/batchServed' })
    async batchServed(ctx, next) {
        let params: {
            invertoryId: string;
            orderId: string;
            operator: { id: string, name: string };
            count: number;
            cartItemId: string;
        }[] = ctx.request.body.params;
        let user = ctx.request.body.user;
        let terminal = ctx.request.body.terminal;
        let storeId = ctx.accept.headers["storeid"];
        let preOrders: Order[] = [];
        for (let p of params) {
            let preOrder = await this.tableSvr.Served(p.invertoryId, p.cartItemId, p.orderId, p.operator, p.count);
            //同步数据
            //同步数据
            this.syncSvr.DomainDataSyncPackage([
                {
                    id: preOrder.id,
                    body: preOrder,
                    entityName: "preOrders"
                }
            ], { storeId: storeId, terminal: terminal, user: user }, { name: "", type: "" });
            preOrders.push(preOrder);
        }

        ctx.response.body = Response.ok("上菜成功！", preOrders);
        await next();
    }

    @route({ method: 'put', path: '/api/table/cancelServed' })
    @RequestDataVerify(new DataVerification.CancelServed())
    async cancelServed(ctx, next) {
        let params: {
            invertoryId: string;
            orderId: string;
            terminal: any;
            user: any;
        } = ctx.request.body;
        let storeId = ctx.accept.headers["storeid"];
        let preOrder = await this.tableSvr.CancelServed(params.invertoryId, params.orderId);

        ctx.response.body = Response.ok("取消上菜成功！", preOrder);

        //数据同步
        this.syncSvr.DomainDataSyncPackage([
            {
                id: preOrder.id,
                body: preOrder,
                entityName: "preOrders"
            }
        ], { storeId: storeId, terminal: params.terminal, user: params.user }, { name: "", type: "" });

        await next();
    }

    @route({ method: 'get', path: '/api/table/getGroupTables/:tableGroupId' })
    async getGroupTables(ctx, next) {
        let tableGroupId: string = ctx.params.tableGroupId;
        let r = await this.tableSvr.GetTablesByGroupId(tableGroupId);
        ctx.response.body = Response.ok("获取成功！", r);
        await next();
    }

    @route({ method: "post", path: "/api/table/lock" })
    @RequestDataVerify(new DataVerification.LockTable())
    async lockTable(ctx, next) {
        let tableId = ctx.request.body.tableId;
        let terminal = ctx.request.body.terminal;

        await this.tableSvr.LockTable(tableId, terminal);
        ctx.response.body = Response.ok("锁定成功！", true);

        await next();
    }
    @route({ method: "post", path: "/api/table/unlock" })
    async unloackTable(ctx, next) {
        let tableId = ctx.request.body.tableId;
        await this.tableSvr.UnlockTable(tableId);
        ctx.response.body = Response.ok("解除锁定成功！", true);

        await next();
    }


    @route({ method: "post", path: "/api/table/finishCleanTable" })
    @RequestLog()
    @RequestDataVerify(new DataVerification.FinishCleanTable())
    async finishCleanTable(ctx, next) {
        let terminal = ctx.request.body.terminal;
        let user = ctx.request.body.user;
        let storeId = ctx.accept.headers["storeid"];

        let r = await this.tableSvr.FinishCleanTable({
            tableId: ctx.request.body.tableId,
            bussers: ctx.request.body.bussers
        });
        ctx.response.body = Response.ok("台桌清理完成", true);

        this.syncSvr.DomainDataSyncPackage(
            [
                {
                    id: r.tableParty.id,
                    body: r.tableParty,
                    entityName: "tableParties"
                }
            ]
            , {
                storeId,
                terminal,
                user
            }
        );

        await next();
    }

    @route({ method: "get", path: "/api/table/lockStatus/:tableId/:terminalId" })
    async getTableLockStatus(ctx, next) {
        let tableId = ctx.params.tableId;
        let terminalId = ctx.params.terminalId;
        let table = await this.tableSvr.GetTableById(tableId);

        let result: any = {};
        if (table.lock && table.lock.terminalId != terminalId) {
            result.isLock = true;
            result.lock = table.lock;
        }
        else {
            result.isLock = false;
        }

        ctx.response.body = Response.ok("查询成功", result);

        await next();
    }

    @route({ method: "post", path: "/api/table/setTableSettled" })
    @RequestDataVerify(new DataVerification.SetTableSettled())
    async setTableSettled(ctx, next) {
        let tableId = ctx.request.body.tableId;
        let terminal = ctx.request.body.terminal;
        let checkoutOrder = ctx.request.body.order;
        let storeId = ctx.accept.headers["storeid"];
        let user = ctx.request.body.user;
        let result = await this.tableSvr.SetTableSettled(tableId, checkoutOrder);
        ctx.response.body = Response.ok("修改成功", result);

        await next();
    }

    @route({ method: 'post', path: "/api/table/getTableFee" })
    async getTableFee(ctx, next) {
        let orderIds: string[] = ctx.request.body.orderIds;
        let result = await this.tableSvr.getTableFee(orderIds);
        ctx.response.body = Response.ok("获取成功", result);
        await next();
    }


    @route({ method: "post", path: "/api/table/cancelTableSettled" })
    @RequestLog()
    @RequestDataVerify(new DataVerification.CancelTableSettled())
    async cancelTableSettled(ctx, next) {
        let tableId = ctx.request.body.tableId;
        let terminal = ctx.request.body.terminal;
        let storeId = ctx.accept.headers["storeid"];
        let user = ctx.request.body.user;
        let cancelReason = ctx.request.body.reason;
        let orderAmountDue = ctx.request.body.amountDue;

        let result = await this.tableSvr.CancelTableSettled(tableId, cancelReason, user, orderAmountDue);

        ctx.response.body = Response.ok("修改成功", result);

        await next();
    }
}
